 //type  即自定义类型 可以像 name:string, 中string一样使用 如 teacher:person
type person = {
  name:string,
  age:number,
}

let a :string |number          //a 可以是两种类型中的一个 （联合类型）
let b : "male"|"female"       //可直接写字面量 b只能是其中一个值
let c :any       //设置any后ts会关闭其监测  用ts就没有意义 （不建议）
let d             //直接声明 会隐式any  （要避免）
let e :unknown    //未知类型  与any类型的区别在与any可以祸害其他变量的类型   any可以赋值别的类型  unknown不能
e = 'hi'  //a = e  => //应为“;”。ts(1005)不能将类型“unknown”分配给类型“string | number”。不能将类型“unknown”分配给类型“number”。
a = e as string  //类型断言  告诉编译器e是string
a = <string>e 
if(typeof e =='string') a= e  //三种解决方式
let f:object     //没有意义 js里都是对象
let g:{name:string;age:number;[propName:string]:any} //一般用这种方式
let h:(a:number,b:number)=>number    //函数
let i : number[]
let j : Array<number>;  //i j  数组的两种方式
let k :[string,string]  //元组 主要是规定了数组长度
/* 
枚举 enum 把所有可能的情况列出来
*/

var Enum;
(function (Enum) {
    Enum[Enum["A"] = 0] = "A";
})(Enum || (Enum = {}));
undefined
console.log(Enum); //{0: 'A', A: 0}
 

enum sex{
  female=0,
  male=1,
}
enum sex2{
  female='0',
  male='1',
}
function test11(val:sex|sex2){
  console.log(val);
}
test11(sex.male)
test11(0)
// test11('0') // 值是number时可以映射不会报错，其他类型时只能test11(sex2.female)表示
test11(sex2.female)

type sexKeys = keyof typeof  sex
type sexVals = `${sex}`;
const yain:sexKeys =  'male'
let l :{name:string,sex:sex}
l = {
  name:'jack',
  sex:sex.female
}


let m :{name:string}&{age:number}&person   //{name:string} ,{age:number} 可用于自定义类型的联合
m = {name:'jack',age:1}

//描述一个对象的类型  如上let f并不实用  一般直接定义出具体的类型 或者用自定义type
let n :{name:string,age:number}
let o :person

//接口用来定义一个类结构 ，用来定义类中应该包含那些属性和方法，同时接口也可以当作类型声明去使用
interface myPerson {
  name:string,
  age:number,
}
let p:myPerson    //和type person 一个效果 
//interface 和type 不同的是 相同的type名只能声明一次   interface可以声明多次  并且会将多次声明的内容整合到一起
interface myPerson {
  sex:number
}
p = {
  name:'jack',
  sex:1,
  age:1
}

//接口可以在定义类的时候限制类的结构，所有的属性不能有实际值，所有的方法都是抽象方法
interface myInter{
   name:string;
   say():void;
}
//implements 类要满足接口的所有结构
class MyInter implements myInter{
  name: string;
  constructor(name:number){
    this.name = name+''
  }
  say(): void {
    throw new Error("Method not implemented.")
  }

}

//这样一个函数如何让其类型安全呢？
// function prop(obj, key) {
//   return obj[key]
// }
function prop<T, Key extends keyof T>(obj: T, key: Key) {
  return obj[key];
}

const user = {
  id: 1,
  name: "Test User",
  points: 0
};

const userName = prop(user, "name"); // const userName : string;



/* 
Pick、Omit、Extract和Exclude
*/

type T0 = Extract<"a" | "b" | "c", "a" | "f">;  //提取 交集  只有a
type T1 = Exclude<"a" | "b" | "c", "a" | "f">;  //排除  前者排除后者 即bc
type T2 = Exclude< "a" | "f","a" | "b" | "c">;  //排除  前者排除后者 即f

const obj = {
  a:1,
  b:'2'
}
type ObjType = typeof obj

//具体的值也是类型
interface ObjType2 {
  a:1,
  b:'2',
  c:true
}

type T3 = Pick< ObjType ,"a" >;  //选择 {a:number}
type T4 = Pick< ObjType2 ,"a" >;  //选择 {a:1}
type T5 = Omit< ObjType ,"a" >;  //排除 {b:string}
type T6 = Omit< ObjType2 ,"a" >;  //排除 {b:'2',c:true}
